package com.example.srm.auth.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.srm.auth.service.TRolePermissionService;
import com.example.srm.auth.service.TRoleService;
import com.example.srm.constant.RolePermissionConstant;
import com.example.srm.domain.TRole;
import com.example.srm.domain.TRolePermission;
import com.example.srm.auth.mapper.TPermissionMapper;
import com.example.srm.auth.mapper.TRolePermissionMapper;
import com.example.srm.auth.mapper.TRoleMapper;
import com.example.srm.domain.tree.Tree;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.*;
import java.util.stream.Collectors;

/**
 *
 */
@Service
@Slf4j
@Transactional
public class TRoleServiceImpl extends ServiceImpl<TRoleMapper, TRole>
    implements TRoleService {
    @Autowired
    private TRoleMapper roleMapper;
    @Autowired
    private TPermissionMapper permissionMapper;
    @Autowired
    private TRolePermissionMapper rpMapper;
    @Autowired
    private TRolePermissionService rpService;

    //查询角色的叶子节点权限
    @Override
    public Set<String> findPermissionIdsById(String id) {
        List<Tree> permissionIdsById = roleMapper.findPermissionIdsById(id);
        return permissionIdsById.stream().map(e->e.getId()).collect(Collectors.toSet());
    }

    /**
     * 分配成功的情况：第一次分配（分配之前用户没有权限）-->允许存在删除失败、新增成功的情况
     *              分配之前有权限-->必须是 删除、新增均成功的情况
     * 其他情况均失败
     * @param id
     * @param permissionIds
     * @return
     */
    @Override
    @Transactional
    public boolean assignmentPermission(String id, String[] permissionIds) {
            //检验参数
            TRole tRole = roleMapper.selectById(id);
            if (tRole==null){return false;}
            //查询所有的权限id
            List<String> allPermissions = permissionMapper.selectList(null).stream().map(e1 -> e1.getId()).collect(Collectors.toList());
            //过滤掉传入参数中在权限id中没有的无效权限id --> 剩下的为数据库存在的即将分配的权限id
            List<String> assignIds = Arrays.stream(permissionIds)
                    .distinct()
                    .filter(e1 -> allPermissions.contains(e1))
                    .collect(Collectors.toList());

            //角色权限关系对象集合
            List<TRolePermission> rpList = assignIds.stream()
                    .map(e1 -> new TRolePermission().setRoleId(id).setPermissionId(e1))
                    .collect(Collectors.toList());

            HashMap<String, Object> map = new HashMap<>();
            map.put(RolePermissionConstant.roleId, id);
            //删除前查询用户的角色集合
            List<TRolePermission> tRolePermissionMap = rpService.listByMap(map);

            boolean remove = rpService.removeByMap(map);
            boolean assign = rpService.saveBatch(rpList);
            //删除失败，新增成功
            if (!remove&&assign){
                //判断是否第一次分配 --> 如果本来就没有角色数据，remove就回返回false。我们只需要新增即可
                if (tRolePermissionMap.isEmpty()){return true;}
                //手动回滚
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                log.error("分配权限出错");
                return false;
            }else if(remove&&assign){
                return true;
            }
        return false;
    }


    /**
     * 将树结点对象集合转为树结构集合
     * @param list
     * @return
     */
    private List<Tree> toTree(List<Tree> list) {
        HashMap<String, Tree> map = new HashMap<>();
        list.forEach(e->map.put(e.getId(),e));

        List<Tree> list1 = new ArrayList<>();

        for (Tree tree : list) {
            Tree parent = map.get(tree.getPid());
            if (parent==null){
                System.out.println(tree.getName()+","+tree.getIndex());
                //解决前端的bug，需要在根节点设置 false
                tree.setChecked(false);
                list1.add(tree);
            }else {
                if (parent.getChildren()==null){
                    parent.setChildren(new LinkedList<>());
                }
                System.out.println(tree.getName()+","+tree.getIndex());
                parent.getChildren().add(tree);
            }
        }
        return list1;
    }
}




